package com.demo.config;

import java.time.LocalDateTime;

import org.apache.ibatis.reflection.MetaObject;
import org.springframework.util.StringUtils;

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import com.baomidou.mybatisplus.core.metadata.TableInfo;
import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
import com.demo.util.Snowflake;

/**
 * MyBatis Plus 元数据处理类 用于自动 注入 id, createTime, updateTime, createUser, updateUser 等字段
 *
 */
public class MyMetaObjectHandler implements MetaObjectHandler {

    /**
     * id类型判断符
     */
    private static final String ID_TYPE = "java.lang.String";

    private static final String FIELD_ID = "id";

    private static final String FIELD_CREATE_USER = "createUser";

    private static final String FIELD_UPDATE_USER = "updateUser";

    private Snowflake snowflake;

    /**
     * @param workerId 终端ID
     * @param dataCenterId 数据中心ID
     */
    public MyMetaObjectHandler(long workerId, long dataCenterId) {
        super();
        snowflake = new Snowflake(workerId, dataCenterId);
    }

    /**
     * 注意：不支持 复合主键 自动注入！！
     * <p>
     * 所有的继承了BaseEntity的实体，在insert时， id： id为空时， 通过IdGenerate生成唯一ID， 不为空则使用传递进来的id createUser, updateUser: 自动赋予
     * 当前线程上的登录人id和companyId createTime, updateTime: 自动赋予 服务器的当前时间
     * <p>
     * 未继承任何父类的实体，且主键标注了 @TableId(value = "xxx", type = IdType.INPUT) 自动注入 主键 主键的字段名称任意
     *
     * @param metaObject
     */
    @Override
    public void insertFill(MetaObject metaObject) {
        // 设置创建时间和创建人
        this.setFieldValByName("updateTime", LocalDateTime.now(), metaObject);
        this.setFieldValByName("createTime", LocalDateTime.now(), metaObject);
        if (this.getFieldValByName("state", metaObject) == null) {
            this.setFieldValByName("state", 1, metaObject);
        }
        // todo 用户id
        this.setFieldValByName(FIELD_CREATE_USER, 1L, metaObject);//系统创建的
        this.setFieldValByName(FIELD_UPDATE_USER, 1L, metaObject);//系统创建的
        
        TableInfo tableInfo = TableInfoHelper.getTableInfo(metaObject.getOriginalObject().getClass());
        if (tableInfo == null || tableInfo.getIdType() == IdType.AUTO) {
            return;
        }
        Long id = snowflake.nextId();
        if (metaObject.hasGetter(FIELD_ID)) {
            Object idVal = ID_TYPE.equals(metaObject.getGetterType(FIELD_ID).getName()) ? String.valueOf(id) : id;
            this.setFieldValByName(FIELD_ID, idVal, metaObject);
            return;
        }
        // id 字段名
        String keyProperty = tableInfo.getKeyProperty();
        if (keyProperty == null) {
            return;
        }
        // 反射得到 主键的值
        Object fieldValue = this.getFieldValByName(keyProperty, metaObject);
        // 判断ID 是否有值，有值就不
        if (fieldValue != null && StringUtils.hasText(fieldValue.toString())) {
            return;
        }
        Object idVal = tableInfo.getKeyType().getName().equalsIgnoreCase(ID_TYPE) ? String.valueOf(id) : id;
        this.setFieldValByName(keyProperty, idVal, metaObject);
    }

    /**
     * 所有的继承了 BaseEntity的实体，在update时， updateUser: 自动赋予 当前线程上的登录人id updateTime: 自动赋予 服务器的当前时间
     *
     * @param metaObject
     */
    @Override
    public void updateFill(MetaObject metaObject) {
        this.setFieldValByName("updateTime", LocalDateTime.now(), metaObject);
        this.setFieldValByName(FIELD_UPDATE_USER, 1L, metaObject);//系统创建的
    }

}
